package ophiux.wechat.template.util.parse.json;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import ophiux.OphiuxWechatTemplateMessageException;
import ophiux.wechat.template.util.json.ExceptionErrorListener;
import ophiux.wechat.template.util.json.JSONReader;
import ophiux.wechat.template.util.json.JSONValidatingReader;
import ophiux.wechat.template.util.parse.EntityConverter;
import ophiux.wechat.template.util.parse.IConvert;
import ophiux.wechat.template.util.parse.Reader;

public class JsonConverter implements IConvert {

	@Override
	public <T> T toEntity(Class<T> clzz, String dataSource)  throws OphiuxWechatTemplateMessageException{
		JSONReader reader = new JSONValidatingReader(new ExceptionErrorListener());
		Object rootObj = reader.read(dataSource);
		if (rootObj instanceof Map<?, ?>) {
			Map<?, ?> rootJson = (Map<?, ?>) rootObj;
			Collection<?> values = rootJson.values();
			for (Object rspObj : values) {
				if (rspObj instanceof Map<?, ?>) {
					Map<?, ?> rspJson = (Map<?, ?>) rspObj;
					return fromJson(rspJson, clzz);
				}
			}
		}
		return null;
	}
	
	
	/**
     * 把JSON格式的数据转换为对象。
     * @param <T> 泛型领域对象
     * @param json JSON格式的数据
     * @param clazz 泛型领域类型
     * @return 领域对象
     * @throws TopException
     */
    public <T> T fromJson(final Map<?, ?> json, Class<T> clzz) throws OphiuxWechatTemplateMessageException {
    	Reader xmlReader = new Reader() {

			@Override
			public boolean isExistNode(String tagNames) {
				return json.containsKey(tagNames);
			}

			@Override
			public Object getNodeValue(String tagNames) {
				 return json.get(tagNames);
			}

			@Override
			public Object getNodeObject(String tagName, Class<?> subType)
					throws OphiuxWechatTemplateMessageException {
				Object tmp = json.get(tagName);
                if (tmp instanceof Map<?, ?>) {
                    Map<?, ?> map = (Map<?, ?>) tmp;
                    return fromJson(map, subType);
                } else {
                    return null;
                }
			}

			@Override
			public List<?> getNodeListObject(String parentName, String tagNames, Class<?> subType) throws OphiuxWechatTemplateMessageException {
				List<Object> listObjs = null;

                Object listTmp = json.get(parentName);
                if (listTmp instanceof Map<?, ?>) {
                    Map<?, ?> jsonMap = (Map<?, ?>) listTmp;
                    Object itemTmp = jsonMap.get(tagNames);
                    if (itemTmp == null && parentName != null) {
                        String listNameStr = parentName.toString();
                        itemTmp = jsonMap.get(listNameStr.substring(0, listNameStr.length() - 1));
                    }
                    if (itemTmp instanceof List<?>) {
                        listObjs = getListObjectsInner(subType, itemTmp);
                    }
                } else if (listTmp instanceof List<?>) {
                    listObjs = getListObjectsInner(subType, listTmp);
                }

                return listObjs;
			}
			
			private List<Object> getListObjectsInner(Class<?> subType, Object itemTmp) throws OphiuxWechatTemplateMessageException {
                List<Object> listObjs;
                listObjs = new ArrayList<Object>();
                List<?> tmpList = (List<?>) itemTmp;
                for (Object subTmp : tmpList) {
                    Object obj = null;
                    if (String.class.isAssignableFrom(subType)) {
                        obj = subTmp;
                    } else if (Long.class.isAssignableFrom(subType)) {
                        obj = subTmp;
                    } else if (Integer.class.isAssignableFrom(subType)) {
                        obj = subTmp;
                    } else if (Boolean.class.isAssignableFrom(subType)) {
                        obj = subTmp;
                    } else if (Date.class.isAssignableFrom(subType)) {
                        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        try {
                            obj = format.parse(String.valueOf(subTmp));
                        } catch (ParseException e) {
                            throw new OphiuxWechatTemplateMessageException(e);
                        }
                    } else if (subTmp instanceof Map<?, ?>) {// object
                        Map<?, ?> subMap = (Map<?, ?>) subTmp;
                        obj = fromJson(subMap, subType);
                    }

                    if (obj != null) {
                        listObjs.add(obj);
                    }
                }
                return listObjs;
            }
    	};
    	return EntityConverter.convert(clzz, xmlReader);
    }
	

	@Override
	public <T> String entityToString(T obj) throws OphiuxWechatTemplateMessageException {
		return null;
	}
	
	
}
